package cn.com.doone.common.uc.web.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.doone.common.uc.infrastructure.DateUtils;
import cn.com.doone.common.uc.utils.DES3;
import cn.com.doone.common.uc.utils.MD5;
import cn.com.doone.common.uc.utils.MessageUtils;
import cn.com.doone.common.uc.utils.StringUtils;
import cn.com.doone.common.uc.web.dao.AppDao;
import cn.com.doone.common.uc.web.dao.GroupDao;
import cn.com.doone.common.uc.web.dao.UserGroupMemberDao;
import cn.com.doone.common.uc.web.dao.UserInfoDao;

@Service
public class AppService {

	private final static Logger logger = LoggerFactory.getLogger(AppService.class);

	@Autowired
	private AppDao appDao;
	
	@Autowired
	private GroupDao groupDao;
	
	@Autowired
	private UserGroupMemberDao userGroupMemberDao;
	
	@Autowired
	private UserInfoDao userInfoDao;

//	private static final String[] grantTypes = {"authorization_code","refresh_token","exist"};
	
	/**
	 * 比对加密
	 * @param paramsMap
	 * @return
	 * @throws Exception 
	 */
	public Map<String,Object> comparisonAuth(Map<String,Object> paramsMap) throws Exception {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		String clientId = paramsMap.get("clientId").toString();
		String plainText = paramsMap.get("plainText").toString();
		
		logger.info("根据client查询应用，client_id="+clientId);
		
		Map<String,Object> appMap = appDao.queryAppInfo(clientId);
		
		logger.info("应用信息:"+appMap);
		
		if(StringUtils.isNull(appMap) || StringUtils.isNull(appMap.get("APP_SECRET"))) {
			resultMap.put("success", false);
			resultMap.put("message", "查无应用信息");
			return resultMap;
		}
		if("1".equals(appMap.get("APP_TYPE"))) {
			return resultMap;
		}
		String appSecret = appMap.get("APP_SECRET").toString();
		String newAuthenticator = MD5.getMD5Str(DES3.encode(plainText,appSecret));
		if(!newAuthenticator.equals(paramsMap.get("authenticator").toString())) {
			resultMap.put("success", false);
			resultMap.put("message", MessageUtils.AUTHENTICATOR_FALSE);
			logger.info(paramsMap.toString());
			return resultMap;
		}
		return resultMap;
	}
	
	/**
	 * 更新应用样式路径
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> updateStyleUrl(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		appDao.updateStyleUrl(paramsMap);
		resultMap.put("success", true);
		resultMap.put("message", MessageUtils.EDIT_SUCCESS);
		return resultMap;
	}
	
	/**
	 * 查询应用分页列表
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> queryAppPageList(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		int page = Integer.parseInt(paramsMap.get("page").toString());
		int limit = Integer.parseInt(paramsMap.get("limit").toString());
		paramsMap.put("start", (page - 1) * limit);
		paramsMap.put("limit", limit);
		List<Map<String,Object>> appList = appDao.queryAppList(paramsMap);
		long count = appDao.countApp(paramsMap);
		resultMap.put("data", appList);
		resultMap.put("total", count);
		resultMap.put("success", true);
		return resultMap;
	}
	
	/**
	 * 应用注册
	 * 
	 * @param paramsMap
	 * @return
	 * @throws Exception 
	 */
	@Transactional(rollbackFor=Exception.class)
	public Map<String, Object> addApp(Map<String, Object> paramsMap) throws Exception {
		//验证应用非空信息
		Map<String, Object> resultMap = this.validNotNull(paramsMap);
		if(!resultMap.isEmpty()) {
			return resultMap;
		}
		//验证appCode不重复
		resultMap = this.countAppCode(paramsMap);
		if(!resultMap.isEmpty()) {
			return resultMap;
		}
		
		//如果租户码不为空时，验证租户码唯一
		if(StringUtils.isNotNull(paramsMap.get("tenantCode"))) {
			resultMap = this.countTenantCode(paramsMap);
			if(!resultMap.isEmpty()) {
				return resultMap;
			}
		}
		
		//验证应用信息		
//		resultMap = this.validAppInfo(paramsMap);
//		if(!resultMap.isEmpty()) {
//			return resultMap;
//		}
		
		//生成appsecret
		paramsMap.put("appSecret", this.createAppSecret());
		
		//补全信息
		paramsMap.put("status", "1");
		this.fillParams(paramsMap);
		
		//添加数据库
		appDao.insertApp(paramsMap);
		
		logger.info("添加应用，应用信息为:"+paramsMap);
		
//		//是否要自动创建顶级租户
//		if(StringUtils.isNotNull(paramsMap.get("tenantCode"))) {
//			//查询是否已有租户
//			Map<String,Object> groupMap = groupDao.queryGroupByTenantCode(paramsMap);
//			if(groupMap.isEmpty()) {
//				//创建租户
//				this.addTenant(paramsMap);
//				//如果已授权删除
//				this.deleteGroupAppAuthorize(paramsMap);
//			}else {
//				//添加userGroupId
//				paramsMap.put("userGroupId", groupMap.get("userGroupId"));
//			}
//			//授权
//			this.addGroupAppAuthorize(paramsMap);
//		}
		resultMap.put("success", true);
		resultMap.put("message", MessageUtils.ADD_SUCCESS);
		resultMap.put("appInfo", paramsMap);
		
		return resultMap;
	}
	
	/**
	 * 根据ID查询应用信息
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> queryAppInfoById(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = appDao.queryAppInfoById(paramsMap);
		resultMap.put("success", true);
		return resultMap;
	}
	
	/**
	 * 修改应用
	 * @param paramsMap
	 * @return
	 * @throws Exception 
	 */
	public Map<String,Object> updateApp(Map<String,Object> paramsMap) throws Exception {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		//验证非空字段
		resultMap = this.validNotNull(paramsMap);
		if(!resultMap.isEmpty()) {
			return resultMap;
		}
		//验证是否同一应用
//		resultMap = this.comparisonAuth(paramsMap);
//		if(!resultMap.isEmpty()) {
//			return resultMap;
//		}
		
		//验证应用信息
//		resultMap = this.validAppInfo(paramsMap);
//		if(!resultMap.isEmpty()) {
//			return resultMap;
//		}
		
		//更新应用信息
		appDao.updateApp(paramsMap);
		
		resultMap.put("success", true);
		resultMap.put("message", MessageUtils.EDIT_SUCCESS);
		resultMap.put("appInfo", paramsMap);
		
		return resultMap;
	}
	
	/**
	 * 改变应用状态
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> changeAppStatus(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		paramsMap.put("updateTime", DateUtils.toDateText(new Date(), "yyyy-MM-dd HH:mm:ss"));
		appDao.editAppStatus(paramsMap);
		//如果是禁用应用，删除应用和组的授权关系
		if("0".equals(paramsMap.get("status"))) {
			appDao.deleteAuthzGroupByClient(paramsMap);
		}
		resultMap.put("success", true);
		resultMap.put("message", MessageUtils.DO_SUCCESS);
		return resultMap;
	}
	
	/**
	 * 查询应用组授权关系
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> queryAppGroupAuthzTreeList(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		paramsMap.put("fkGroupId", "0");
		paramsMap.put("groupType", "1");
		paramsMap.put("status", "1");
		//查询顶级组列表
		List<Map<String,Object>> groupList = groupDao.queryGroupListByFkGroupId(paramsMap);
		//查询组应用授权列表
		List<Map<String,Object>> groupAuthzList = groupDao.queryAuthzGroupByAppInfoId(paramsMap);
		for(Map<String,Object> groupMap: groupList) {
			groupMap.put("label", groupMap.get("groupName"));
			for(int i=0;i<groupAuthzList.size();i++) {
				Map<String,Object> authzMap = groupAuthzList.get(i);
				if (groupMap.get("userGroupId").toString().equals(authzMap.get("userGroupId").toString())) {
					groupMap.put("checked", true);
					break;
				}
			}
		}
		resultMap.put("data", groupList);
		resultMap.put("success", true);
		resultMap.put("message", MessageUtils.DO_SUCCESS);
		return resultMap;
	}
	
	/**
	 * 应用授权组
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> editAppGroupAuthz(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		//删除所有的应用和组关系
		appDao.deleteAuthzGroupByClient(paramsMap);
		if(StringUtils.isNull(paramsMap.get("userGroupIds"))) {
			resultMap.put("success", true);
			resultMap.put("message", MessageUtils.DO_SUCCESS);
			return resultMap;
		}
		List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
		String[] groupIds = paramsMap.get("userGroupIds").toString().split(",");
		for(String groupId: groupIds) {
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userGroupId", groupId);
			map.put("appInfoId", paramsMap.get("appInfoId"));
			list.add(map);
		}
		appDao.batchInsertAppGroupAuthz(list);
		resultMap.put("success", true);
		resultMap.put("message", MessageUtils.DO_SUCCESS);
		return resultMap;
	}
	
	/**
	 * 删除应用
	 * @param paramsMap
	 * @return
	 * @throws Exception 
	 */
	@Transactional(rollbackFor=Exception.class)
	public Map<String,Object> deleteApp(Map<String,Object> paramsMap) throws Exception {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		//删除应用
		appDao.deleteApp(paramsMap);
		//查询应用ID
		Map<String,Object> appMap = appDao.queryAppInfo(paramsMap.get("clientId").toString());
		paramsMap.put("appInfoId", appMap.get("APP_INFO_ID"));
		//查询应用绑定的组
		List<Map<String,Object>> groupList = groupDao.queryAuthzGroupByAppInfoId(paramsMap);
		if(groupList.size()==0) {
			resultMap.put("success", true);
			resultMap.put("message", MessageUtils.DELETE_SUCCESS);
			return resultMap;
		}
		//删除应用绑定的组
		appDao.deleteAuthzGroupByClient(paramsMap);
		//查询组是否还有绑定其他应用，如果没有则删除组和对应的用户
		long count = appDao.countAppByAuthzGroupId(groupList);
		if(count > 0) {
			resultMap.put("success", true);
			resultMap.put("message", MessageUtils.DELETE_SUCCESS);
			return resultMap;
		}
		//根据顶级租户查询子组
		groupList = groupDao.queryGroupByAuthzGroup(groupList);
		//删除组
		groupDao.batchDeleteGroupByGroupId(groupList);
		//查询和组关联的用户
		List<Map<String,Object>> userList = userGroupMemberDao.queryUserByGroupList(groupList);
		if(userList.size()>0) {
			//统计没有组的用户
			List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
			userList.forEach(userMap -> {
				if(Integer.parseInt(userMap.get("count").toString()) == 0) {
					list.add(userMap);
				}
			});
			//删除组用户关系
			userGroupMemberDao.batchDeleteUserGroupMemberByGroup(groupList);
			//删除用户
			userInfoDao.batchDeleteUserInfo(list);
		}
		resultMap.put("success", true);
		resultMap.put("message", MessageUtils.DELETE_SUCCESS);
		return resultMap;
	}
	
	/**
	 * 根据clientId查询应用信息
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> queryAppInfoByClientId(String clientId) {
		if(StringUtils.isNull(clientId)) {
			return null;
		}
		return appDao.queryAppInfo(clientId);
	}
	
	/**
	 * 验证clientId是否重复
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> validClientId(Map<String,Object> paramsMap) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		if(StringUtils.isNull(paramsMap.get("appCode"))) {
			resultMap.put("success", false);
			resultMap.put("message", "参数不能为空");
			return resultMap;
		}
		resultMap = this.countAppCode(paramsMap);
		if(resultMap.isEmpty()) {
			resultMap.put("success", true);
			resultMap.put("message", "可以使用的appCode");
		}
		return resultMap;
	}
	
	/**
	 * 根据clientId和appSecret查询应用是否存在
	 * @param paramsMap
	 * @return
	 */
	public Map<String,Object> validClientByClientIdAndAppSecret(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		long count = appDao.countClientByClientIdAndAppSecret(paramsMap);
		if(count != 1){
			resultMap.put("success", false);
			resultMap.put("message", "应用不存在");
			return resultMap;
		}
		return resultMap;
	}
	
	/**
	 * 验证appCode是否重复
	 * @param paramsMap
	 * @return
	 */
	private Map<String,Object> countAppCode(Map<String,Object> paramsMap) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		// 检查appCode是否重复
		String appCode = paramsMap.get("appCode").toString();
		long count = appDao.countAppClientId(appCode);
		if (count > 0) {
			resultMap.put("success", false);
			resultMap.put("message", "client重复");
			return resultMap;
		}
		return resultMap;
	}
	
	/**
	 * 验证租户码是否重复
	 * @param paramsMap
	 * @return
	 */
	private Map<String,Object> countTenantCode(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		String tenantCode = paramsMap.get("tenantCode").toString();
		long count = appDao.countTenantCode(tenantCode);
		if(count > 0) {
			resultMap.put("success", false);
			resultMap.put("message", "租户编码重复");
			return resultMap;
		}
		return resultMap;
	}
	
	/**
	 * 验证应用信息
	 * @param paramsMap
	 * @return
	 */
//	private Map<String,Object> validAppInfo(Map<String,Object> paramsMap) {
//		Map<String, Object> resultMap = new HashMap<String,Object>();
//		
//		// 检查uri
//		if(StringUtils.isNotNull(paramsMap.get("appUri"))) {
//			String redirectUri = paramsMap.get("appUri").toString();
//			if (!StringUtils.validRedirectUri(redirectUri)) {
//				resultMap.put("success", false);
//				resultMap.put("message", "appUri格式不正确");
//				return resultMap;
//			}
//		}
//		// 检查redirect_uri
//		if(StringUtils.isNotNull(paramsMap.get("redirectUri"))) {
//			String redirectUri = paramsMap.get("redirectUri").toString();
//			if (!StringUtils.validRedirectUri(redirectUri)) {
//				resultMap.put("success", false);
//				resultMap.put("message", "redirectUri格式不正确");
//				return resultMap;
//			}
//		}
//		//检查appType,当不为1时scope必填
//		if(StringUtils.isNotNull(paramsMap.get("appType")) && "2".equals(paramsMap.get("appType").toString())) {
//			if(StringUtils.isNull(paramsMap.get("scope"))) {
//				resultMap.put("success", false);
//				resultMap.put("message", "当appType不为1时，参数scope为必须");
//				return resultMap;
//			}
//		}
//		//当有租户码时，组名称必须有
//		if(StringUtils.isNotNull(paramsMap.get("tenantCode"))) {
//			if(StringUtils.isNull(paramsMap.get("company"))) {
//				resultMap.put("success", false);
//				resultMap.put("message", "当需要自动创建租户时，参数company不能为空");
//				return resultMap;
//			}
//		}
//		if(StringUtils.isNotNull(paramsMap.get("grantTypes"))) {
//			//认证模式验证
//			String p_grantType = paramsMap.get("grantTypes").toString();
//			String[] p_grantTypes = p_grantType.split(",");
//			for (String gt : p_grantTypes) {
//				boolean bol = false;
//				for(String grantType:grantTypes) {
//					if(gt.equals(grantType)) {
//						bol = true;
//						break;
//					}
//				}
//				if(!bol) {
//					resultMap.put("success", false);
//					resultMap.put("message", "不支持的授权方式:"+gt);
//					break;
//				}
//			}
//		}
//		return resultMap;
//	}
	
	/**
	 * 验证字段不为空
	 * @param paramsMap
	 * @return
	 */
	private Map<String,Object> validNotNull(Map<String,Object> paramsMap) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		
		if(StringUtils.isNull(paramsMap.get("appName")) || StringUtils.isNull(paramsMap.get("appCode"))
				|| StringUtils.isNull(paramsMap.get("redirectUri"))) {
			resultMap.put("success", false);
			resultMap.put("message", "参数不完整");
		}
		
		return resultMap;
	}
	
	/**
	 * 生成appSecret
	 * @return
	 */
	private String createAppSecret() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}
	
	/**
	 * 补全信息
	 * @param paramsMap
	 */
	private void fillParams(Map<String,Object> paramsMap) {
		if(StringUtils.isNull(paramsMap.get("appType"))) {
			paramsMap.put("appType", "1");
		}
		if(StringUtils.isNull(paramsMap.get("resourceIds"))) {
			paramsMap.put("resourceIds", "os-resource");
		}
		if(StringUtils.isNull(paramsMap.get("scope"))) {
			paramsMap.put("scope", "read write");
		}
		if(StringUtils.isNull(paramsMap.get("grantType"))) {
			paramsMap.put("grantType", "authorization_code,refresh_token");
		}
		if(StringUtils.isNull(paramsMap.get("roles"))) {
			paramsMap.put("roles", "21");
		}
		if(StringUtils.isNull(paramsMap.get("accessTokenValidity"))) {
			paramsMap.put("accessTokenValidity", "-1");
		}
		if(StringUtils.isNull(paramsMap.get("refreshTokenValidity"))) {
			paramsMap.put("refreshTokenValidity", "-1");
		}
		if(StringUtils.isNull(paramsMap.get("archived"))) {
			paramsMap.put("archived", "0");
		}
		if(StringUtils.isNull(paramsMap.get("trusted"))) {
			paramsMap.put("trusted", "1");
		}
	}
	
	/**
	 * 添加顶级组(租户)
	 * @param paramsMap
	 * @throws Exception
	 */
//	private void addTenant(Map<String,Object> paramsMap) throws Exception {
//		paramsMap.put("groupName", paramsMap.get("company"));
//		paramsMap.put("status", 1);
//		paramsMap.put("fkGroupId", 0);
//		paramsMap.put("updateTime", new Date());
//		
//		//查询最后的顶级组
//		Map<String,Object> tenantMap = groupDao.queryTenantGroup();
//		
//		logger.info("查询最后添加的顶级组,组代码为:"+tenantMap);
//		
//		if(tenantMap.isEmpty()) {
//			paramsMap.put("groupCode", "1001");
//		}else {
//			String groupCode = tenantMap.get("groupCode").toString();
//			try {
//				paramsMap.put("groupCode", Integer.parseInt(groupCode)+1);
//			} catch (Exception e) {
//				logger.error("格式化组代码失败,组代码为:"+groupCode);
//				throw new Exception("组代码错误");
//			}
//		}
//		
//		//添加组
//		groupDao.addUserGroup(paramsMap);
//		logger.info("添加组;"+paramsMap);
//		
//		paramsMap.put("userGroup", paramsMap);
//	}
	
	/**
	 * 删除应用与组授权
	 * @param paramsMap
	 */
//	private void deleteGroupAppAuthorize(Map<String,Object> paramsMap) {
//		Map<String,Object> authzMap = new HashMap<String,Object>();
//		authzMap.put("userGroupId", paramsMap.get("userGroupId"));
//		authzMap.put("appInfoId", paramsMap.get("appInfoId"));
//		
//		appDao.deleteAppGroupAuthorize(authzMap);
//		logger.info("删除应用与组授权:"+authzMap);
//	}
	
	/**
	 * 添加应用与组授权
	 * @param paramsMap
	 */
//	private void addGroupAppAuthorize(Map<String,Object> paramsMap) {
//		Map<String,Object> authzMap = new HashMap<String,Object>();
//		
//		authzMap.put("userGroupId", paramsMap.get("userGroupId"));
//		authzMap.put("appInfoId", paramsMap.get("appInfoId"));
//		authzMap.put("authTime", new Date());
//		authzMap.put("defaultAuth", "1");
//		
//		appDao.insertAppGroupAuthorize(authzMap);
//		
//		logger.info("添加应用与组授权:"+authzMap);
//	}

}
